package edu.nctu.csie.jichang.spring;

import java.io.File;
import java.io.FileReader;
import java.util.Properties;

import org.springframework.beans.PropertyValue;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.TypedStringValue;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader;
import org.springframework.beans.factory.xml.XmlReaderContext;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;

public class EnhanceBeanDefinitionDocumentReader extends DefaultBeanDefinitionDocumentReader{

	
	private static final String FILE_BEAN_NAME = "database";
	private static final String FILE_PROPERTY_NAME = "fileName";
	
	@Override
	protected void importBeanDefinitionResource(Element pElement) {
		
		String tOriginalLocation = pElement.getAttribute(RESOURCE_ATTRIBUTE);
		String tNewLocation      = tOriginalLocation;
		if (!StringUtils.hasText(tOriginalLocation)) {
			getReaderContext().error("Resource location must not be empty", pElement);
			return;
		}
		
		tNewLocation = getNewLocation(tOriginalLocation);
		
		if(!tOriginalLocation.equalsIgnoreCase(tNewLocation)){
			pElement.setAttribute(RESOURCE_ATTRIBUTE, tNewLocation);
			System.out.println("Dynamic set url [" + tOriginalLocation +"=>" + tNewLocation +"]");
		}
		
		super.importBeanDefinitionResource(pElement);
	}

	private String getNewLocation(String pOriginalLocation) {
		if(pOriginalLocation.indexOf("#{")>=0){
			try {
				Expression tExpression = new Expression(pOriginalLocation);
				// #{ database.databaseType=='POSTGRESQL' ? 'postgresql/ienc.xml' : 'mssql/ienc.xml'}
				if(tExpression.isExpression()){
					String tKey        = tExpression.getKey();                                                // database.databaseType
					String tSettingKey = null;                                                                // POSTGRESQL
					XmlReaderContext tXmlReaderContext = getReaderContext();
					BeanDefinitionRegistry tRegistry = tXmlReaderContext.getRegistry();
					if (tRegistry instanceof DefaultListableBeanFactory) {
						DefaultListableBeanFactory tBeanFactory = (DefaultListableBeanFactory) tRegistry;
						// from property file get value => POSTGRESQL
						tSettingKey = getValueFromPropertyFile(tKey,tXmlReaderContext, tBeanFactory);
						// from xml file get value database.databaseType = ? POSTGRESQL
						if(tSettingKey==null){
							tSettingKey = getValueFromXmlFile(tKey,tBeanFactory);
						}
						if(tSettingKey!=null){
							return tExpression.getValue(tSettingKey);
						}
					}
				}else{
					return  tExpression.getReturnValue();
				}
			} catch (Exception e) {
				System.err.println("Can't handle dymanic import resource");
			}
		}
		return pOriginalLocation;
	}

	private String getValueFromXmlFile(String pKey, DefaultListableBeanFactory pBeanFactory) {
		PropertyValue tPropertyValue;
		String[] tBeanProperty = pKey.split("\\.");
		tPropertyValue = pBeanFactory.getBeanDefinition(tBeanProperty[0]).getPropertyValues().getPropertyValue(tBeanProperty[1]);
		if (tPropertyValue.getValue() instanceof TypedStringValue) {
			return ((TypedStringValue) tPropertyValue.getValue()).getValue();
		}
		return null;
	}

	private String getValueFromPropertyFile(String pKey,XmlReaderContext pXmlReaderContext,DefaultListableBeanFactory pBeanFactory) throws Exception{
		File tFile = pXmlReaderContext.getResource().getFile();
		BeanDefinition tBeanDefinition = pBeanFactory.getBeanDefinition(FILE_BEAN_NAME);
		PropertyValue tPropertyValue = tBeanDefinition.getPropertyValues().getPropertyValue(FILE_PROPERTY_NAME);
		if (tPropertyValue.getValue() instanceof TypedStringValue) {
			String tOverrideFileNamePath = tFile.getParentFile().getAbsolutePath()+"\\"+((TypedStringValue) tPropertyValue.getValue()).getValue();
			File tOverrideFile = new File(tOverrideFileNamePath);
			if(tOverrideFile.exists()){
				Properties tProperties = new Properties();
				tProperties.load(new FileReader(tOverrideFile));
				return tProperties.getProperty(pKey);
			}
		}
		return null;
	}
}
